/**
 * parser header
 * 
 * @author strlst <e11907086@student.tuwien.ac.at>
 * @date 2020-01-02
 * @brief contains method definitions useful for both the server and client
 * when dealing with input that needs to be parsed
 */

#ifndef PARSER_H
#define PARSER_H

#include <errno.h>
#include <getopt.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "def.h"
#include "client.h"

/**
 * @brief translates which file was requested in an http request given both
 * a document root `doc_root` and default index file `index`
 * @details effectively translates by creating the composite of all three
 * supplied values, while not disregarding the semantics of a url: should
 * `req_file` end with a '/', the index file be appended, otherwise not.
 * delivers a result that must subsequently be freed outside the scope of
 * this function.
 *
 * is a server function.
 * @param doc_root directory containing all the files to be served, effectively
 * limiting the scope of which files can be requested via `req_file`, as
 * explained in `req_file` parameter description
 * @param index default index file, will be appended depending on req_file
 * @param req_file the component of the request, must always begins with a '/'
 * @return a string constituting a real filepath that can subsequently be used
 * for I/O
 */
char *translate_requested_file(char*, char*, char*);

/**
 * @brief takes a buffer (long string) containing the first line of a http
 * response and extracts the response code
 * @details it is assumed that the response code can be found within the
 * characters up until the first newline '\n'.
 * this is in accordance with the definition supplied in RFC 7230 (HTTP 1.1)
 * but will cause issues with servers prepending an empty line.
 *
 * will cause abnormal exit upon encountering a critical error.
 *
 * will cause abnormal exit upon encountering a protocol error, which occurs
 * if:
 * - the first line is not a valid HTTP response header start-line
 * - the HTTP version is not "HTTP/1.1"
 * - the response value is not an unsigned number
 * (the error code of "protocol error" can be found in the def header)
 *
 * is a client function.
 * @param program program name to print in the event of errors
 * @param buf (long) string containing the very first characters of an http
 * response
 * @param buf_len integer containing the length of buf (must be accurate)
 * @return a uint16_t response code
 */
uint16_t parse_response_code(char*, char*, int);

/**
 * @brief takes a buffer (long string) containing the first line of a http
 * request and extracts the requested file by translating it into a real
 * filepath
 * @details it is assumed that the requested file can be found within the
 * characters up until the first newline '\n'.
 * this is in accordance with the definition supplied in RFC 7230 (HTTP 1.1)
 * but will cause issues with servers prepending an empty line.
 *
 * will cause abnormal exit upon encountering a critical error.
 *
 * will return NULL and propagate a ret value of RQ_PROTOCOL_ERROR upon
 * encountering a protocol error, which occurs if:
 * - the first line is not a valid HTTP request header start-line
 * - the HTTP version is not "HTTP/1.1"
 * - the requested file contains instances of "/../", this is done in order
 *   not to leak any possibly sensitive files
 *
 * will propagate a ret value of RQ_NOT_IMPLEMENTED upon encountering an
 * unimplemented value, which occurs if:
 * - the request method is not "GET"
 *
 * in any other event, ret will be RQ_OK and the return value a newly
 * allocated string (which must subsequently be freed!)
 *
 * is a server function.
 * @param program program name to print in the event of errors
 * @param buf (long) string containing the very first characters of an http
 * request
 * @param buf_len integer containing the length of buf (must be accurate)
 * @param ret pointer to a uint16_t value, used to communicate the result
 * of the parse operation
 * @return a string constituting a real filepath that can subsequently be used
 */
char *parse_request_file(char*, char*, int, uint16_t*);

/**
 * @brief takes a url and extracts the webserver component
 * @details return value subsequently has to be freed
 *
 * is a client function.
 * @param program program name to print in the event of errors
 * @param url_str string containing a url in its entirety, in the form of:
 * http://webserver/path
 * @return a string constituting a webserver that can subsequently be used
 * by `getaddrinfo(...)` for example
 */
char *parse_url_webserver(char*, char*);

/**
 * @brief takes a url and extracts the path component
 * @details return value subsequently has to be freed
 *
 * is a client function.
 * @param program program name to print in the event of errors
 * @param url_str string containing a url in its entirety, in the form of:
 * http://webserver/path
 * @return a string constituting a path that can subsequently be used
 * in an http request for the path component
 */
char *parse_url_path(char*, char*);

/**
 * @brief takes a url and extracts the file component
 * @details return value subsequently has to be freed
 *
 * is a client function.
 * @param program program name to print in the event of errors
 * @param url_str string containing a url in its entirety, in the form of:
 * http://webserver/path, or in an alternate representation:
 * http://webserver/.../file
 * @return a string constituting a file that can subsequently be used
 * in case the user wants to save the file locally without having to
 * specify a file name
 */
char *parse_url_file(char*, char*);

/**
 * @brief takes a url string and extracts all relevant component to form an
 * instance of the url structure
 * @details return value subsequently has to be freed.
 * will cause an abnormal exit in the case of a critical error
 *
 * is a client function.
 * @param program program name to print in the event of errors
 * @param url_str string containing a url in its entirety, in the form of:
 * http://webserver/path, or in an alternate representation:
 * http://webserver/.../file
 * @return a url with all of it's components initialized, provided the url
 * was valid
 */
url parse(char*, char*);

#endif